/** @format */

import fs from 'fs'
import path from 'path'

const ignore = /(\/\*[\s\S]*?\*\/|<!--[\s\S]*?-->|\/\/.*)/gi
const ignoreConsole = /console\.[\s\S]*?\)/gi
const br = /\s*\n\s*/gi

function validateString(str) {
  const regex = /[\u4e00-\u9fa5a-zA-Z]/
  return regex.test(str)
}

// const hasChineseOrLetter = /[\u4e00-\u9fff]|[a-zA-Z\s]+/; //中文或字母
// const isNotOnlyDigitsOrSpecialChars = /^(?![\d\W_]+$)[a-zA-Z\d\W_]+$)/; //数字或特殊字符
export function checkString(str, globalConfig) {
  const newStr = str
    .replace(/\&nbsp;/g, '')
    ?.replace(/\$\{([^}]+)}/g, '')
    ?.replace('\\n', '')
  if (!newStr?.trim()) return false
  if (
    (str.indexOf('$tc(') !== -1 && str.indexOf('tc(') !== -1) ||
    str.indexOf(globalConfig.i18nT) !== -1
  )
    return false
  return validateString(str)
}

// 处理vue动态属性
function preVaild(idx, newStr, globalConfig, curword, file, number) {
  try {
    // 匹配上一个就为真
    const somebool = globalConfig.hotToken.some((item) => {
      let validCharacter = ''
      let i = 1
      //向前多找的容错范围 4
      const strLen = item.length + 4
      while (validCharacter.length < strLen) {
        validCharacter = newStr[idx - i] + validCharacter
        i++
        // 最多循环40次
        if (i > 40) {
          break
        }
      }
      // 默认false
      let bool = false
      for (let i = 0; i < globalConfig.hotToken.length; i++) {
        let hotidx = validCharacter.indexOf(item)
        const prev = validCharacter.slice(-3)
        if (
          hotidx !== -1 &&
          validCharacter.slice(-1) !== ',' &&
          prev.indexOf('t(') === -1 &&
          prev.indexOf('h(') === -1
        ) {
          bool = true
          break
        }
      }
      return bool
    })
    return somebool
  } catch (e) {
    console.error(e)
  }
}

// 处理en中js的词语
export function scriptEnHandle(str, globalConfig, file) {
  str = str.replace(/\s*import.*?\;/gi, '')
  str = str.replace(/http(s)*:\/\//gi, '')
  str = str.replace(ignore, '').replace(ignoreConsole, '').replace(br, '')
  let arr = []
  let curIdx = -1
  const rep1 = /(`|'|")([\s\S]*?)\1/gi
  str = str.replace(rep1, function (code, $1, $2) {
    if (checkString($2, globalConfig)) {
      arr.push($2)
      curIdx++
      return `needFind_${curIdx}`
    } else {
      return code
    }
  })
  let word = []
  // 开始扫描hot区
  // 清除了文本中所有的空格
  let newStr = str.replace(/\s/gi, '')
  arr.forEach((item, idx) => {
    // 找到出现的位置
    const IDX = newStr.indexOf(`needFind_${idx}`)
    // 进行前置判断
    if (preVaild(IDX, newStr, globalConfig, item, file, idx)) {
      // 验证通过
      let placeholderIdx = -1
      word.push(
        item?.replace(/\${[\s\S]*?}/g, function (word, $0) {
          ++placeholderIdx
          return `{placeholder_${placeholderIdx}}`
        })
      )
      // console.log(word)
    }
  })
  return word || []
}

// 处理cn中js中的词语
export function scriptCnHandle(str) {
  str = str
    .replace(ignore, '')
    .replace(ignoreConsole, '')
    .replace(/([\s\S]*?)\?([\s\S]*?)\:/gi, function (word, $1, $2) {
      return `threeYuan ? ${$2} :`
    })
    .replace(/\n/gi, '')
  let newStr = str
  const arr = []
  const rep1 = /(`|'|")([\s\S]*?)\1/gi
  newStr = newStr.replace(rep1, function (word, $1, $2) {
    if (cnReg.test($2)) {
      arr.push($2)
      return ''
    }
  })
  return arr
}
export function strToObj(str) {
  const esModule = /export\s*default/gi
  const commonModule = /module\.exports\s*=/gi
  let data
  eval(`data = ${str?.replace(esModule, '')?.replace(commonModule, '')}`)
  return data
}

//加载当前模块所有文件
export const loadChildModule = (filePath, itemConf, level = 0) => {
  // 单文件
  const statRoot = fs.lstatSync(filePath)
  if (!statRoot.isDirectory()) {
    return [filePath]
  }
  // 文件夹
  let arrFiles = []
  const files = fs.readdirSync(filePath)
  const excludes = itemConf?.exclude || []
  for (let i = 0; i < files.length; i++) {
    const item = files[i]
    if (level == 0 && excludes.includes(item)) {
      continue
    }
    const stat = fs.lstatSync(filePath + '/' + item)
    if (stat.isDirectory()) {
      arrFiles = arrFiles.concat(loadChildModule(filePath + '/' + item))
    } else {
      const jsReg = /\.js$/
      const vueReg = /\.vue$/
      if (jsReg.test(item) || vueReg.test(item)) {
        arrFiles.push(filePath + '/' + item)
      }
    }
  }
  return arrFiles
}

export function rmDir(dirPath) {
  if (fs.existsSync(dirPath)) {
    fs.readdirSync(dirPath).forEach((file, index) => {
      const curPath = path.join(dirPath, file)
      if (fs.statSync(curPath).isDirectory()) {
        // 如果是文件夹
        rmDir(curPath) // 递归删除文件夹
      } else {
        // 如果是文件
        fs.unlinkSync(curPath) // 删除文件
      }
    })
    fs.rmdirSync(dirPath) // 删除空文件夹
  }
}

export function isFileExisted(pathWay) {
  return fs.existsSync(pathWay)
}

export function newParseAttrs(attrsString, globalConfig) {
  if (!attrsString?.trim()) return []
  const regex = /[:@]*[\w\-\.]+\s*=\s*('|")([\s\S]*?)\1/gi
  const matchArr = attrsString.match(regex) || []
  const attrsArray = matchArr?.map((match) => {
    const str = match.trim()
    const idx = str?.indexOf('=')
    const attribute = str.substring(0, idx)
    const value = str.substring(idx + 1)
    return {
      attr: str,
      name: attribute?.trim(),
      value: value.substring(1, value.length - 1),
    }
  })
  const attrsData = []
  const attrsDataObj = []
  // 因为en 没发确定边界，只能重点匹配这些关键字
  const hot = globalConfig?.attrHotToken
  attrsArray.forEach((attr) => {
    hot.forEach((item) => {
      if (attr.name === item && checkString(attr.value, globalConfig)) {
        attrsData.push(attr.value)
        attrsDataObj.push({
          attr: attr.attr,
          name: attr.name,
          value: attr.value,
        })
      }
    })
  })
  return {
    attrsArray: attrsArray,
    attrsData: attrsData,
    attrsDataObj: attrsDataObj,
  }
}
